﻿using System.Collections.Generic;
using System.Linq;

using SIG.Model;
using SIG.Repository;

using SIG.Infrastructure.Logging;
using SIG.Infrastructure.Cache;
using SIG.Infrastructure.Configs;
using SIG.Resources;
using System.Linq.Expressions;
using System;
using SIG.Basic.Extensions;
using SIG.Model.Announcements;
using SIG.Resources.Admin;

namespace SIG.Service
{
    public class AnnouncementService: EntityService<Announcement>, IAnnouncementService
    {
     
        private readonly IAnnouncementRepository _announcementRepository;
        private readonly ILoggingService _loggingService;
        private readonly ICacheService _cacheService;

        public AnnouncementService(IAnnouncementRepository announcementRepository, ILoggingService loggingService, ICacheService cacheService)
            : base(announcementRepository, cacheService, loggingService)
        {
           
            _announcementRepository = announcementRepository;
            _loggingService = loggingService;
            _cacheService = cacheService;
        }

        public IEnumerable<Announcement> GetActiveAnnouncements()
        {
            //get list
            var key = $"{EntityNames.Announcement}_ActiveList";

            List<Announcement> announcements;
            if (SettingsManager.Announcement.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    announcements = (List<Announcement>)_cacheService.Get(key);

                }
                else
                {
                    announcements = _announcementRepository.GetFilteredElements(c=>c.Active).ToList();
                    _cacheService.Set(key, announcements, SettingsManager.Announcement.CacheDuration);
                }
            }
            else
            {
                announcements = _announcementRepository.GetFilteredElements(c => c.Active).ToList();
            }

            return announcements;
        }

        public List<Announcement> GetPagedActiveElements(int pageIndex, int pageSize, string keyword, out int totalCount)
        {

            //get list count
            var keyCount = $"{EntityNames.Announcement}_Active_ListCount_{keyword}";

            var totalIQuery = _announcementRepository.GetAllElements().Where(m=>m.Active);
            if (!string.IsNullOrEmpty(keyword))
                totalIQuery = totalIQuery.Where(g => g.Body.Contains(keyword));


            if (SettingsManager.Announcement.EnableCaching)
            {
                if (_cacheService.IsSet(keyCount))
                {
                    totalCount = (int)_cacheService.Get(keyCount);
                }
                else
                {
                    totalCount = totalIQuery.Count();
                    _cacheService.Set(keyCount, totalCount, SettingsManager.Announcement.CacheDuration);
                }
            }
            else
            {
                totalCount = totalIQuery.Count();
            }


            //get list
            var key = $"{EntityNames.Announcement}_Active_List_{pageIndex}_{pageSize}_{keyword}";

            List<Announcement> announcement;
            Expression<Func<Announcement, bool>> filter = g => g.Active;
            Expression<Func<Announcement, bool>> filterByKeyword = g => g.Body.Contains(keyword);

            if (!string.IsNullOrEmpty(keyword))
                filter = filter.AndAlso(filterByKeyword);

            if (SettingsManager.Announcement.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    announcement = (List<Announcement>)_cacheService.Get(key);
                }
                else
                {
                    announcement = _announcementRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false).ToList();
                    _cacheService.Set(key, announcement, SettingsManager.Announcement.CacheDuration);
                }
            }
            else
            {
                announcement = _announcementRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false).ToList();
            }

            return announcement;

        }
        public List<Announcement> GetPagedElements(int pageIndex, int pageSize, string keyword, out int totalCount)
        {

            //get list count
            var keyCount = $"{EntityNames.Announcement}_ListCount_{keyword}";

            var totalIQuery = _announcementRepository.GetAllElements();
            if (!string.IsNullOrEmpty(keyword))
                totalIQuery = totalIQuery.Where(g => g.Body.Contains(keyword));
         

            if (SettingsManager.Announcement.EnableCaching)
            {
                if (_cacheService.IsSet(keyCount))
                {
                    totalCount = (int)_cacheService.Get(keyCount);
                }
                else
                {
                    totalCount = totalIQuery.Count();
                    _cacheService.Set(keyCount, totalCount, SettingsManager.Announcement.CacheDuration);
                }
            }
            else
            {
                totalCount = totalIQuery.Count();
            }


            //get list
            var key = $"{EntityNames.Announcement}_List_{pageIndex}_{pageSize}_{keyword}";

            List<Announcement> announcement;
            Expression<Func<Announcement, bool>> filter = g => true;
            Expression<Func<Announcement, bool>> filterByKeyword = g => g.Body.Contains(keyword);
         

            if (!string.IsNullOrEmpty(keyword))
                filter = filter.AndAlso(filterByKeyword);
           


            if (SettingsManager.Announcement.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    announcement = (List<Announcement>)_cacheService.Get(key);

                }
                else
                {
                    announcement = _announcementRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false).ToList();
                    _cacheService.Set(key, announcement, SettingsManager.Announcement.CacheDuration);
                }
            }
            else
            {
                announcement = _announcementRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false).ToList();
            }

            return announcement;

        }

        public IEnumerable<Announcement> LatesterAnnouncements(int count)
        {
            var key = $"{EntityNames.Announcement}s_Latester_{count}";

            if (!SettingsManager.Announcement.EnableCaching)
            {
                return _announcementRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active, false).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Announcement>)_cacheService.Get(key);

            }

            var announcementList = _announcementRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active, false).ToList();
            _cacheService.Set(key, announcementList, SettingsManager.Announcement.CacheDuration);


            return announcementList;
        }
    }
}
